home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 014 / gi / gi.c next >
C/C++ Source or Header  |  1995-03-17  |  13KB  |  419 lines

  1. /**********************************************************
  2. *                                                         *
  3. *   gi - a DeluxePaint to C data converter                *
  4. *                                                         *
  5. *   Copyright (c) 1986,  Michael J. Farren                *
  6. *   This program may be freely distributed by any means   *
  7. *   desired, but may not be sold in any form.             *
  8. *                                                         *
  9. **********************************************************/
  10.  
  11. #include <stdio.h>
  12. #undef NULL
  13. #include <exec/types.h>
  14.  
  15. struct BitMapHeader {
  16.    UWORD w,h;      /* raster width, height, in pixels */
  17.    WORD  x,y;      /* pixel position for saved image  */
  18.    UBYTE nplanes;   /* number of bit planes in source  */
  19.    UBYTE masking;   /* masking technique         */
  20.    UBYTE compression;   /* compression algorithm      */
  21.    UBYTE pad1;      /* padding to justify next entry   */
  22.    UWORD transColor;   /* transparent "color number"      */
  23.    UBYTE xAsp, yAsp;   /* x:y aspect ratio         */
  24.    WORD  pageW, pageH;   /* source "page" size in pixels    */
  25.    }  bmhd;
  26. UBYTE Cmap[96],old_cmap[96];   /*  32 color storage */
  27. APTR *(raster_lines[400][6]);   /* pointers to raster lines in bit planes */
  28. LONG colors_in_byte[8], colors_used[32], tran_table[32];
  29. LONG twopowers[7] = { 1, 2, 4, 8, 16, 32, 64 };
  30.  
  31. main(argc, argv)
  32. int argc;
  33. char *argv[];
  34. {
  35.    WORD bytes_per_line;    /* Number of bytes per raster line */
  36.    FILE *i_file, *o_file;
  37.    UBYTE *buff_pointer, *body_data;    /* storage pointers */
  38.    UBYTE *data_pointer, *buff_pointer_save;
  39.    LONG body_data_size, buff_size;     /* size storage */
  40.    LONG i, j, k, temp;     /* various temporary variables */
  41.    UBYTE tempbyte;
  42.  
  43.    /*  Check arguments, and try to open i/o files  */
  44.  
  45.    if(argc != 3) {
  46.       printf("\nUsage -> getimage <input file> <output file>\n");
  47.       exit(20);
  48.    }
  49.  
  50.    if((i_file = fopen(argv[1], "r")) == 0 ) {
  51.       printf("\nCould not open input file %s!\n", argv[1]);
  52.       exit(20);
  53.    }
  54.  
  55.    if((o_file = fopen(argv[2], "w")) == 0 ) {
  56.       printf("\nCould not open output file %s!\n", argv[2]);
  57.       exit(20);
  58.    }
  59.  
  60.    /* Files are O.K. - skip over first 20 bytes ("FORM", length, "ILBM",
  61.       "BMHD", length) */
  62.  
  63.    printf("\nReading input file...\n");
  64.    if(fseek(i_file, 20L, 0)) read_error();
  65.  
  66.    /* Now, read in the BMHD structure */
  67.  
  68.    chkread(&bmhd, sizeof(struct BitMapHeader), i_file);
  69.  
  70.    /* Skip the CMAP label, and read in the color map length, then the color
  71.       map data.  We assume that the color map length accurately reflects
  72.       the number of bit planes, so don't bother to check the header entry
  73.       bmhd.nplanes.  Also, all Amiga color maps will have an even number of
  74.       entries, so don't bother padding the read out.  */
  75.  
  76.    if(fseek(i_file, 4L, 1)) read_error();    /* skip the label */
  77.    chkread(&temp, sizeof(LONG), i_file);          /* read the length */
  78.  
  79.    i = 0;                  /* and read in the map */
  80.    while( i < temp)
  81.       chkread(&Cmap[i++], 1, i_file);
  82.  
  83.    /* Now, check the next header.  If it isn't "GRAB", this isn't a
  84.       brush file, so get out  */
  85.  
  86.    chkread(&temp, sizeof(LONG), i_file);
  87.    if(temp != ('G'<<24 | 'R'<<16 | 'A'<<8 | 'B')) {
  88.       printf("\nThe input file is not a DeluxePaint brush file!\n");
  89.       exit(20);
  90.    }
  91.  
  92.    /* It's probably a brush file.  Skip the next 12 bytes (the GRAB length,
  93.       the GRAB coords, and the "BODY" label), then get the body length,
  94.       then read the body data into body_data[] */
  95.  
  96.    if(fseek(i_file, 12L, 1)) read_error();
  97.    chkread(&body_data_size, sizeof(LONG), i_file);
  98.    body_data = AllocMem(body_data_size, NULL);
  99.    chkread(body_data, body_data_size, i_file);
  100.  
  101.    /* Now, start the good stuff.  First, allocate enough memory to hold
  102.       the entire bitmap for the image. */
  103.  
  104.    bytes_per_line = (bmhd.w & 7 ? bmhd.w+8 : bmhd.w) >> 3;
  105.    if(bytes_per_line & 1) bytes_per_line++;
  106.  
  107.    buff_size = bytes_per_line * bmhd.h * bmhd.nplanes;
  108.    buff_pointer = AllocMem(buff_size, NULL );
  109.    buff_pointer_save = buff_pointer;
  110.    data_pointer = body_data;
  111.  
  112.    /* Next, go through the file line by line, bit plane by bit plane,
  113.       and extract the image data, putting it into bitmap.  As this is
  114.       being done, save pointers to each line in the raster_lines array. */
  115.  
  116.    for(i=0; i!=bmhd.h; i++) {         /* # of lines high */
  117.       for(j=0; j!=bmhd.nplanes; j++) {      /* # of planes      */
  118.          raster_lines[i][j] = buff_pointer;   /* set the pointer */
  119.          if(bmhd.compression == 1) {
  120.  
  121.     /* if compressed, decompress */
  122.  
  123.             expand_map(bytes_per_line, buff_pointer, &data_pointer);
  124.          }
  125.          else {
  126.             for(k=0; k!=bytes_per_line; k++) {
  127.                *(buff_pointer+k) = *(data_pointer++);
  128.             }
  129.          }
  130.          buff_pointer += bytes_per_line;
  131.       }
  132.    }
  133.  
  134.    FreeMem(body_data, body_data_size);   /* deallocate the body data block */
  135.  
  136. /* Now, go through the data, determining the different colors used  */
  137.  
  138. calc_color:
  139.  
  140.    printf("\nAnalyzing data...");
  141.    for(i=0; i!=twopowers[bmhd.nplanes]; colors_used[i++]=0);
  142.    for(i=0; i!=bmhd.h; i++) {
  143.       for(j=0; j!=bmhd.w; j++) {
  144.          colors_used[get_a_bit(i,j)] = 1;
  145.       }
  146.    }
  147.  
  148. /*  Show the current color register stuff */
  149.  
  150. start_over:
  151.  
  152.    printf("\nCurrent color register assignments for this picture are:\n");
  153.  
  154.    for(i=0; i!=twopowers[bmhd.nplanes]; i++) {
  155.       if(colors_used[i]) {
  156.          printf("%2d -> R:%2d G:%2d B:%2d      ",
  157.             i, Cmap[i*3]>>4, Cmap[i*3+1]>>4, Cmap[i*3+2]>>4);
  158.       }
  159.       else {
  160.          printf("%2d -> Not Used            ",i);
  161.       }
  162.       if(i&1) printf("\n");
  163.    }
  164.  
  165. /*  Check to see if the user wants to change any of the register assignments.
  166.     If so, do the appropriate transformations of the data base. */
  167.  
  168.    printf("\nDo you wish to change assignments (y or n)? ");
  169.    do {
  170.       tempbyte = getchar();
  171.    }
  172.    while( (tempbyte!='y')
  173.        && (tempbyte!='Y')
  174.        && (tempbyte!='n')
  175.        && (tempbyte!='N'));
  176.  
  177.    if((tempbyte == 'y') || (tempbyte == 'Y')) {
  178.       if(get_new_colors()) goto start_over; /* If invalid change, loop */
  179.       printf("\nProcessing color change...");
  180.       for(i=0; i!=96; old_cmap[i] = Cmap[i++]);   /* Save old colors */
  181.       for(i=0; i!=bmhd.h; i++) {      /* lines */
  182.          for(j=0; j!=bmhd.w; j++) {      /* bits */
  183.             temp = get_a_bit(i,j);
  184.             if(tran_table[temp]!=-1) {
  185.                put_a_bit(i,j,tran_table[temp]);
  186.                for(k=0; k!=3; k++) {            /* swap colors */
  187.                   Cmap[tran_table[temp]*3+k] = old_cmap[temp*3+k];
  188.                }
  189.             }
  190.          }
  191.       }
  192.       goto calc_color;    /* show the new arrangement */
  193.    }
  194.  
  195. /* Now, write the data to the output file, color map first, then data,
  196.    plane by plane, line by line */
  197.  
  198.    printf("\nWriting output file...");
  199.  
  200. /* Output a few statistics */
  201.  
  202.    fprintf(o_file, "/*   Image %s  */\n",argv[1]);
  203.    fprintf(o_file, "     Width:    %d\n",bmhd.w);
  204.    fprintf(o_file, "     Height:   %d\n",bmhd.h);
  205.    fprintf(o_file, "     Depth:    %d  */\n",bmhd.nplanes);
  206.  
  207. /* Start with the color map */
  208.  
  209.    fprintf(o_file, "/* Color Map (xxxxxx = unused color) */\n\n");
  210.    fprintf(o_file, "USHORT map[] = {\n");
  211.    for(i=0; i!=twopowers[bmhd.nplanes]; i++) {
  212.       fprintf(o_file, "   ");
  213.       if(colors_used[i])
  214.          make_word((Cmap[i*3]<<4)+Cmap[i*3+1]+(Cmap[i*3+2]>>4), o_file);
  215.       else fprintf(o_file, "xxxxxx");
  216.       if(i!=twopowers[bmhd.nplanes]-1) fprintf(o_file, ",");
  217.       fprintf(o_file, "\n");
  218.    }
  219.    fprintf(o_file, "};\n\n");
  220.  
  221. /* Now, do the data */
  222.  
  223.    fprintf(o_file, "/* Image Data */\n\n");
  224.    fprintf(o_file, "UWORD %s[%d] = {\n", argv[1], buff_size/2);
  225.    for(i=0; i!=bmhd.nplanes; i++) {
  226.       fprintf(o_file, "/* Bit Plane #%d */\n\n", i);
  227.       for(j=0; j!=bmhd.h; j++) {
  228.          fprintf(o_file, "   ");
  229.          buff_pointer = raster_lines[j][i];
  230.          for(k=0; k<bytes_per_line; ) {
  231.             tempbyte = *(buff_pointer+(k++));
  232.             make_word((tempbyte << 8) | *(buff_pointer+(k++)), o_file);
  233.             fprintf(o_file, ",");
  234.          }
  235.          fprintf(o_file, "\n");
  236.       }
  237.       fprintf(o_file, "\n");
  238.    }
  239.    fseek(o_file, -3, 1);     /* back up to wipe out the last comma */
  240.    fprintf(o_file, "\n};\n");
  241.  
  242. /* Close up, clean up, and get out */
  243.  
  244.    fclose(o_file);
  245.    fclose(i_file);
  246.    printf("\n");
  247.    FreeMem(buff_pointer_save, buff_size);
  248. }
  249.  
  250. /*  read_error - called if a read error occured */
  251.  
  252. read_error()
  253. {
  254.    printf("\nRead error in input file, aborting\n");
  255.    exit(20);
  256. }
  257.  
  258. /* chkread - reads from input file, checking for errors */
  259.  
  260. chkread(ptr, size, fd)
  261. APTR *ptr;
  262. WORD size;
  263. FILE *fd;
  264. {
  265.    WORD readin;
  266.    readin = fread(ptr, size, 1, fd);
  267.    if(readin != 1) read_error();
  268. }
  269.  
  270. /* expand_map - decompresses data compressed with the byte_run encoding
  271.                 scheme described in the IFF document.  A signed byte, x,
  272.                 is read from the input block.  If the signed value of x
  273.                 is negative, but not -128 ( 0x80 ), the next byte is read
  274.                 and is placed in the output block (-x+1) times.  If the
  275.                 signed value is positive, the next (x+1) bytes are copied
  276.                 directly to the output block.  If the signed value is -128,
  277.                 no operation is performed.
  278. */
  279.  
  280.  
  281. expand_map(length, pointer, data_pointer)
  282. WORD length;
  283. UBYTE *pointer;
  284. UBYTE **data_pointer;
  285. {
  286.  
  287.    WORD minus128 = -128;
  288.    WORD temp;
  289.    BYTE tempbyte;
  290.    UBYTE tempubyte;
  291.  
  292.    while( length > 0 )   {
  293.       tempbyte = *((*data_pointer)++);
  294.       temp = tempbyte;
  295.       if (temp >= 0) {
  296.          temp += 1;
  297.          length-=temp;
  298.          do {
  299.             *(pointer++) = *((*data_pointer)++);
  300.          }
  301.          while (--temp > 0);
  302.       }
  303.       else if (temp != minus128) {
  304.          temp = (-temp) + 1;
  305.          length -= temp;
  306.          tempubyte = *((*data_pointer)++);
  307.          do {
  308.             *(pointer++) = tempubyte;
  309.          }
  310.          while (--temp > 0);
  311.       }
  312.    }
  313. }
  314.  
  315. /* get_a_bit - returns the color value of the bit at location x,y in the
  316.                image.
  317. */
  318.  
  319. get_a_bit(y, x)
  320. LONG y, x;
  321. {
  322.    LONG xbyte, xbit,i;
  323.    UBYTE tempbyte, color;
  324.    UBYTE *pointer;
  325.  
  326.    color = 0;                         /* start with no color */
  327.    xbyte =x>>3;                       /* xbyte = the byte location of x */
  328.    xbit = (1<<(x&7));                 /* xbit = the mask for the bit */
  329.    for(i=0; i!=bmhd.nplanes; i++) {   /* do all the planes */
  330.       pointer = raster_lines[y][i];          /* get the base address */
  331.       tempbyte = *(pointer + xbyte);         /* get the proper byte  */
  332.       if(tempbyte & xbit) color |= (1 << i); /* OR in the color bit  */
  333.    }
  334.    return color;
  335. }
  336.  
  337. /* put_a_bit - sets a given bit to a given color */
  338.  
  339. put_a_bit(y, x, color)
  340. LONG y, x, color;
  341. {
  342.    LONG xbyte, xbit, i;
  343.    UBYTE *pointer;
  344.    UBYTE tempbyte;
  345.  
  346.    for(i=0; i!=bmhd.nplanes; i++) {
  347.       xbyte = x>>3;
  348.       xbit = (1 << (x & 7));
  349.       pointer = raster_lines[y][i];
  350.       tempbyte = *(pointer + xbyte);   /* get the appropriate byte */
  351.       tempbyte &= 0xff-xbit;           /* mask off the proper bit  */
  352.       if(color & twopowers[i]) {       /* if the color bit is set, */
  353.          tempbyte |= xbit;             /* set the bit in the byte  */
  354.       }
  355.       *(pointer + xbyte) = tempbyte;   /* save the modified byte   */
  356.    }
  357. }
  358.  
  359. /* get_new_colors - get the users choices for register assignments */
  360.  
  361. get_new_colors()
  362. {
  363.    int i,j;
  364.  
  365.    for(i=0; i!=twopowers[bmhd.nplanes]; tran_table[i++]=-1); /* reset */
  366.    for(i=1; i!=twopowers[bmhd.nplanes]; i++) {
  367.       if(colors_used[i]) {     /* for each color used in the original */
  368. getnew:
  369.          printf("\nOld color register %2d (R:%2d G:%2d B:%2d) new number:",
  370.             i, Cmap[i*3]>>4, Cmap[i*3+1]>>4, Cmap[i*3+2]>>4);
  371.          scanf("%d", &j);
  372.          if((j<1) || (j>=twopowers[bmhd.nplanes])) {
  373.             printf("\nRegister number must be greater than zero, and less than %2d.",
  374.                twopowers[bmhd.nplanes]);
  375.             printf("\nTry again.");
  376.             goto getnew;
  377.          }
  378.          tran_table[i] = j;
  379.       }
  380.    }
  381.  
  382. /* Check the translation table for duplicated register assignments. */
  383.  
  384.    for(i=1; i!=twopowers[bmhd.nplanes]-1; i++) {
  385.       for(j=i+1; j!=twopowers[bmhd.nplanes]; j++) {
  386.          if((tran_table[i]==-1) || (tran_table[j]==-1)) continue;
  387.          if(tran_table[i] == tran_table[j]) {
  388.             printf("\nDuplicate color register assignment - try again.");
  389.             return -1;
  390.          }
  391.       }
  392.    }
  393.    return 0;
  394. }
  395.  
  396. /* make_word - outputs a string representing a four-digit hex number */
  397.  
  398. make_word(num, fp)
  399. UWORD num;
  400. FILE *fp;
  401. {
  402.    char temp[10];
  403.  
  404.    sprintf(temp, "0000%x\0", num);
  405.    fprintf(fp, "0x%s", &temp[strlen(temp)-4]);
  406. }
  407.  
  408. #ifdef MANX    /* Manx C does not have strchr() */
  409. char *strchr (s, c)
  410. char *s;
  411. char c;
  412. {
  413.     while (*s && *s != c) {
  414.         s++;
  415.     }
  416.     return (*s == c ? s : (char *)0);
  417. }
  418. #endif MANX
  419.